package templates

import (
	"fmt"
	"time"
	"strings"
)

type ReportData struct {
	GeneratedAt        time.Time
	Manifests         []Manifest
	Packages          []Package
	Vulnerabilities   []Vulnerability
	MalwareDetections []MalwareDetection
	PackagePopularity []PopularityMetric
	PolicyViolations  []PolicyViolation
	PackageCount      int
	VulnCount         int
	Ecosystems        []string
}

type Manifest struct {
	Path      string
	Ecosystem string
	Packages  []Package
}

type Package struct {
	Name      string
	Version   string
	Ecosystem string
	VulnCount int
	Source    string
}

type Vulnerability struct {
	ID           string
	Package      string
	Version      string
	Severity     string
	Description  string
	Link         string
}

type MalwareDetection struct {
	Package string
	Version string
	Type    string
	Source  string
	Details string
}

type PopularityMetric struct {
	Package      string
	Version      string
	Downloads    int
	Stars        int
	Contributors int
	LastUpdated  string
}

type PolicyViolation struct {
	ID             string
	PolicyName     string
	Description    string
	Solution       string
	PackageName    string
	PackageVersion string
}

// Helper functions for badge classes
func getSeverityBadgeClass(vulnCount int) string {
	if vulnCount >= 5 {
		return "badge-critical"
	} else if vulnCount >= 3 {
		return "badge-high"
	} else if vulnCount >= 1 {
		return "badge-medium"
	}
	return "badge-low"
}

func getSeverityBadgeClassFromString(severity string) string {
    switch strings.ToUpper(severity) {
    case "CRITICAL":
        return "badge-critical"
    case "HIGH":
        return "badge-high"
    case "MEDIUM":
        return "badge-medium"
    case "LOW":
        return "badge-low"
    default:
        return "badge-info"
    }
}

func getMalwareBadgeClass(malType string) string {
    switch strings.ToUpper(malType) {
    case "MALWARE":
        return "badge-malware"
    case "SUSPICIOUS":
        return "badge-suspicious"
    default:
        return "badge-info"
    }
}

templ VetScanReport(data ReportData) {
	<!DOCTYPE html>
	<html lang="en">
		<head>
			<meta charset="UTF-8"/>
			<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
			<title>Vet Scan Report</title>
			<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"/>
			<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css"/>
			<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css"/>
			<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
			@VetScanStyles()
		</head>
		<body class="animate__animated animate__fadeIn">
			@VetScanHeader(data.GeneratedAt)
			<div class="container mb-5">
				@VetScanSummary(data)
				@VetScanTabs(data)
			</div>
			@VetScanFooter()
			@VetScanScripts(data)
		</body>
	</html>
}

templ VetScanFooter() {
	<footer>
		<div class="container">
			<div class="row">
				<div class="col-md-6">
					<h5>About Vet</h5>
					<p>Vet is a tool for analyzing dependencies in software projects to identify vulnerabilities, malware, and policy violations.</p>
				</div>
				<div class="col-md-6 text-md-end">
					<p>Generated by <a href="https://github.com/safedep/vet">safedep/vet</a></p>
				</div>
			</div>
		</div>
	</footer>
}

templ VetScanScripts(data ReportData) {
	<!-- JavaScript Libraries -->
	<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
	<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
	<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
}

templ VetScanStyles() {
	<style>
		:root {
			--primary-color: #0366d6;
			--primary-rgb: 3, 102, 214;
			--danger-color: #dc3545;
			--warning-color: #f0ad4e;
			--info-color: #5bc0de;
			--success-color: #28a745;
			--low-severity: #5bc0de;
			--medium-severity: #f0ad4e;
			--high-severity: #fd7e14;
			--critical-severity: #dc3545;
			--bg-color: #f6f8fa;
			--card-bg: #ffffff;
			--text-color: #f0f6fc;
			--border-color: #e1e4e8;
			--card-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
			--hover-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
			--stats-primary: #0366d6;
			--stats-info: #5bc0de;
			--stats-danger: #dc3545;
			--stats-warning: #f0ad4e;
		}

		body {
			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
			line-height: 1.6;
			color: var(--text-color);
			background-color: var(--bg-color);
			margin: 0;
			padding: 0;
			transition: background-color 0.3s ease, color 0.3s ease;
		}

		.header {
			background: linear-gradient(135deg, #051937, #004d7a, #0077B6);
			color: white;
			padding: 30px 0;
			margin-bottom: 40px;
			border-bottom: 1px solid rgba(255, 255, 255, 0.1);
			box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
		}

		.nav-tabs {
			border-bottom: 1px solid var(--border-color);
			margin-bottom: 25px;
		}

		.nav-tabs .nav-link {
			font-weight: 600;
			padding: 10px 16px;
			border-radius: 6px 6px 0 0;
			color: var(--text-color);
			opacity: 0.8;
			margin-right: 5px;
			border: 1px solid transparent;
			transition: all 0.2s ease;
		}

		.nav-tabs .nav-link:hover:not(.active) {
			border-color: rgba(0,0,0,0.05);
			background-color: rgba(0,0,0,0.02);
			opacity: 0.9;
		}

		.nav-tabs .nav-link.active {
			background-color: var(--card-bg);
			border-color: var(--border-color) var(--border-color) var(--card-bg);
			color: var(--primary-color);
			font-weight: 700;
			transform: translateY(-2px);
			opacity: 1;
			transition: transform 0.2s ease, background-color 0.3s ease, border-color 0.3s ease;
		}

		.nav-tabs .nav-link i {
			margin-right: 6px;
		}

		.card {
			border-radius: 10px;
			box-shadow: var(--card-shadow);
			margin-bottom: 20px;
			border: 1px solid var(--border-color);
			background-color: var(--card-bg);
			transition: transform 0.2s, box-shadow 0.2s, background-color 0.3s ease;
		}

		.card:hover {
			transform: translateY(-2px);
			box-shadow: var(--hover-shadow);
		}

		.card-header {
			background-color: var(--bg-color);
			border-bottom: 1px solid var(--border-color);
			font-weight: 600;
			transition: background-color 0.3s ease;
		}

		.badge-critical {
			background-color: var(--critical-severity);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-high {
			background-color: var(--high-severity);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-medium {
			background-color: var(--medium-severity);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-low {
			background-color: var(--low-severity);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-info {
			background-color: var(--info-color);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-malware {
			background-color: var(--danger-color);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.badge-suspicious {
			background-color: var(--warning-color);
			color: white;
			font-weight: 600;
			padding: 0.35em 0.65em;
			border-radius: 4px;
		}

		.table th {
			font-weight: 600;
			border-top: none;
			border-bottom-width: 1px;
			text-transform: uppercase;
			font-size: 0.8rem;
			letter-spacing: 0.5px;
			color: #23272b !important;
		}

		.code-snippet {
			background-color: var(--bg-color);
			border: 1px solid var(--border-color);
			border-radius: 6px;
			margin: 10px 0;
			overflow-x: auto;
			font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
			transition: background-color 0.3s ease, border-color 0.3s ease;
		}

		.code-snippet pre {
			margin: 0;
			padding: 10px;
			font-size: 0.85em;
			tab-size: 4;
		}

		.code-snippet .line-number {
			color: #57606a;
			text-align: right;
			padding-right: 10px;
			user-select: none;
			border-right: 1px solid #ddd;
		}

		.stats-card {
			text-align: center;
			padding: 20px 15px;
			transition: all 0.3s ease;
			border-radius: 10px;
			height: 100%;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
		}

		.stats-card:hover {
			transform: translateY(-5px);
			box-shadow: var(--hover-shadow);
		}

		.stats-card .icon {
			font-size: 2.2rem;
			margin-bottom: 12px;
			opacity: 0.9;
		}

		.number {
			font-size: 1.8rem;
			font-weight: 700;
			margin-bottom: 5px;
			color: #f0f6fc;
		}

		.stats-card .label {
			font-size: 0.95rem;
			color: #6a737d;
			font-weight: 500;
		}

		.filter-bar {
			background-color: var(--card-bg);
			padding: 15px;
			border-radius: 8px;
			margin-bottom: 20px;
			border: 1px solid var(--border-color);
			transition: background-color 0.3s ease, border-color 0.3s ease;
		}

		.summary-box {
			padding: 25px;
			margin-bottom: 30px;
			border-radius: 10px;
			background-color: var(--card-bg);
			border: 1px solid var(--border-color);
			box-shadow: var(--card-shadow);
			transition: background-color 0.3s ease, border-color 0.3s ease;
		}

		.tab-pane {
			padding: 20px 0;
			animation: fadeIn 0.5s;
			min-height: 300px;
		}

		@keyframes fadeIn {
			from { opacity: 0; transform: translateY(10px); }
			to { opacity: 1; transform: translateY(0); }
		}

		footer {
			background-color: #24292e;
			color: #fff;
			padding: 35px 0;
			margin-top: 60px;
			border-top: 1px solid rgba(255, 255, 255, 0.1);
			box-shadow: 0 -4px 15px rgba(0, 0, 0, 0.1);
		}

		footer h5 {
			font-weight: 600;
			color: #fff;
		}

		footer p {
			color: rgba(255, 255, 255, 0.8);
			font-size: 0.9rem;
		}

		footer a {
			color: var(--primary-color);
			text-decoration: none;
			transition: color 0.2s ease;
		}

		footer a:hover {
			color: var(--primary-color);
			text-decoration: underline;
		}

		.btn-primary {
			background-color: var(--primary-color);
			border-color: var(--primary-color);
			box-shadow: 0 2px 4px rgba(3, 102, 214, 0.2);
			font-weight: 500;
			transition: all 0.2s ease;
		}

		.btn-primary:hover {
			transform: translateY(-1px);
			box-shadow: 0 4px 8px rgba(3, 102, 214, 0.3);
			background-color: var(--primary-color);
			filter: brightness(110%);
		}

		/* Dark mode styles */
		@media (prefers-color-scheme: dark) {
			:root {
				--bg-color: #0d1117;
				--card-bg: #161b22;
				--text-color: #e6edf3;
				--border-color: #30363d;
				--card-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
				--hover-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
				--primary-color: #58a6ff;
				--primary-rgb: 88, 166, 255;
				--stats-primary: #58a6ff;
				--stats-info: #56d4fa;
				--stats-danger: #f85149;
				--stats-warning: #e3b341;
			}

			.table th {
                background-color: #22304e !important;
                color: #f5f7fa !important;
			}

			/* Dark theme table striping */
			/* Unified table row background for all data rows in dark mode */
			table tbody tr td {
				background-color: #23272b !important;
				color: #f5f7fa !important;
			}

			.btn-primary {
				box-shadow: 0 2px 4px rgba(88, 166, 255, 0.2);
			}

			.btn-primary:hover {
				box-shadow: 0 4px 8px rgba(88, 166, 255, 0.3);
			}

			footer {
				background-color: #161b22;
				border-top: 1px solid var(--border-color);
			}

			footer a {
				color: var(--primary-color);
			}
		}
	</style>
}

templ VetScanHeader(generatedAt time.Time) {
	<div class="header">
		<div class="container">
			<div class="d-flex align-items-center justify-content-between">
				<h1 class="mb-0">
					<i class="bi bi-shield-check"></i>
					Vet Scan Report
				</h1>
				<span class="text-light">Generated: { generatedAt.Format("2006-01-02 15:04:05") }</span>
			</div>
		</div>
	</div>
}

templ VetScanSummary(data ReportData) {
	<div class="row mb-4">
		<div class="col-12">
			<div class="summary-box animate__animated animate__fadeInUp">
				<h2 class="mb-4"><i class="bi bi-clipboard-data me-2"></i>Summary</h2>
				<div class="row">
					<div class="col-md-3 mb-3">
						<div class="card stats-card h-100">
							<div class="icon" style="color: var(--stats-primary)">
								<i class="bi bi-file-text"></i>
							</div>
							<div class="number">{ fmt.Sprintf("%d", len(data.Manifests)) }</div>
							<div class="label">Manifest<span class="d-none d-sm-inline">s</span></div>
						</div>
					</div>
					<div class="col-md-3 mb-3">
						<div class="card stats-card h-100">
							<div class="icon" style="color: var(--stats-info)">
								<i class="bi bi-box"></i>
							</div>
							<div class="number">{ fmt.Sprintf("%d", data.PackageCount) }</div>
							<div class="label">Package<span class="d-none d-sm-inline">s</span></div>
						</div>
					</div>
					<div class="col-md-3 mb-3">
						<div class="card stats-card h-100">
							<div class="icon" style="color: var(--stats-danger)">
								<i class="bi bi-exclamation-triangle"></i>
							</div>
							<div class="number">{ fmt.Sprintf("%d", data.VulnCount) }</div>
							<div class="label">Vuln<span class="d-none d-sm-inline">erabilities</span></div>
						</div>
					</div>
					<div class="col-md-3 mb-3">
						<div class="card stats-card h-100">
							<div class="icon" style="color: var(--stats-warning)">
								<i class="bi bi-bug"></i>
							</div>
							<div class="number">{ fmt.Sprintf("%d", len(data.MalwareDetections)) }</div>
							<div class="label">Malware<span class="d-none d-sm-inline">&nbsp; Detections</span></div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
}

templ VetScanTabs(data ReportData) {
	<ul class="nav nav-tabs" id="mainTabs" role="tablist">
		<li class="nav-item" role="presentation">
			<button class="nav-link active" id="manifests-tab" data-bs-toggle="tab" data-bs-target="#manifests" type="button" role="tab" aria-controls="manifests" aria-selected="true">
				<i class="bi bi-file-text"></i>Manifests
			</button>
		</li>
		<li class="nav-item" role="presentation">
			<button class="nav-link" id="packages-tab" data-bs-toggle="tab" data-bs-target="#packages" type="button" role="tab" aria-controls="packages" aria-selected="false">
				<i class="bi bi-box"></i>Packages
			</button>
		</li>
		<li class="nav-item" role="presentation">
			<button class="nav-link" id="vulns-tab" data-bs-toggle="tab" data-bs-target="#vulns" type="button" role="tab" aria-controls="vulns" aria-selected="false">
				<i class="bi bi-exclamation-triangle"></i>Vulnerabilities
			</button>
		</li>
		<li class="nav-item" role="presentation">
			<button class="nav-link" id="malware-tab" data-bs-toggle="tab" data-bs-target="#malware" type="button" role="tab" aria-controls="malware" aria-selected="false">
				<i class="bi bi-bug"></i>Malware Info
			</button>
		</li>
		<li class="nav-item" role="presentation">
		  <button class="nav-link" id="policy-tab" data-bs-toggle="tab" data-bs-target="#policy" type="button" role="tab" aria-controls="policy" aria-selected="false">
		    <i class="bi bi-shield-exclamation"></i> Policy Violations
		  </button>
		</li>
		<li class="nav-item" role="presentation">
			<button class="nav-link" id="popularity-tab" data-bs-toggle="tab" data-bs-target="#popularity" type="button" role="tab" aria-controls="popularity" aria-selected="false">
				<i class="bi bi-graph-up"></i>Popularity
			</button>
		</li>

	</ul>
	<div class="tab-content">
		@ManifestsTab(data.Manifests)
		@PackagesTab(data.Packages, data.Ecosystems)
		@VulnerabilitiesTab(data.Vulnerabilities)
		@MalwareTab(data.MalwareDetections)
		@PopularityTab(data.PackagePopularity)
		@PolicyViolationsTab(data.PolicyViolations)
	</div>
}

templ ManifestsTab(manifests []Manifest) {
	<div class="tab-pane fade show active" id="manifests" role="tabpanel" aria-labelledby="manifests-tab">
		<div class="card mt-4">
			<div class="card-header d-flex justify-content-between align-items-center">
				<h5 class="mb-0 text-white"><i class="bi bi-file-text me-2 text-white"></i>Manifest Files</h5>
			</div>
			<div class="card-body">
				<table class="table table-striped" id="manifestsTable">
					<thead>
						<tr>
							<th>Path</th>
							<th>Ecosystem</th>
							<th>Package Count</th>
						</tr>
					</thead>
					<tbody>
						for _, manifest := range manifests {
							<tr class="">
								<td>{ manifest.Path }</td>
								<td>{ manifest.Ecosystem }</td>
								<td>{ fmt.Sprintf("%d", len(manifest.Packages)) }</td>
							</tr>
						}
					</tbody>
				</table>
			</div>
		</div>
	</div>
}

templ PackagesTab(packages []Package, ecosystems []string) {
	<div class="tab-pane fade" id="packages" role="tabpanel" aria-labelledby="packages-tab">
		<div class="alert alert-info mb-3">
			<i class="bi bi-info-circle me-2"></i> This tab shows all detected packages across all manifests.
		</div>
		<div class="card">
			<div class="card-header">
				<h5 class="mb-0 text-white">Packages</h5>
			</div>
			<div class="card-body">
				<table class="table table-striped" id="packagesTable">
					<thead>
						<tr>
							<th>Name</th>
							<th>Version</th>
							<th>Ecosystem</th>
							<th>Vulnerabilities</th>
							<th>Source</th>
						</tr>
					</thead>
					<tbody>
						for _, pkg := range packages {
							<tr>
								<td>{ pkg.Name }</td>
								<td>{ pkg.Version }</td>
								<td>{ pkg.Ecosystem }</td>
								<td>
									if pkg.VulnCount > 0 {
										<span class={ fmt.Sprintf("badge rounded-pill %s", getSeverityBadgeClass(pkg.VulnCount)) }>
											{ fmt.Sprintf("%d", pkg.VulnCount) }
										</span>
									} else {
										<span class="badge bg-success">0</span>
									}
								</td>
								<td>{ pkg.Source }</td>
							</tr>
						}
					</tbody>
				</table>
			</div>
		</div>
	</div>
}

templ VulnerabilitiesTab(vulnerabilities []Vulnerability) {
	<div class="tab-pane fade" id="vulns" role="tabpanel" aria-labelledby="vulns-tab">
		<div class="card">
			<div class="card-header">
				<h5 class="mb-0 text-white">Vulnerabilities</h5>
			</div>
			<div class="card-body">
				<table class="table table-striped" id="vulnsTable">
					<thead>
						<tr>
							<th>ID</th>
							<th>Package</th>
							<th>Severity</th>
							<th>Description</th>
							<th>Fixed Version</th>
						</tr>
					</thead>
					<tbody>
						for _, vuln := range vulnerabilities {
							<tr class="">
								<td>
									<a href={ vuln.Link } target="_blank">{ vuln.ID }</a>
								</td>
								<td>{ vuln.Package }</td>
								<td>
									<span class={ fmt.Sprintf("badge rounded-pill %s", getSeverityBadgeClassFromString(vuln.Severity)) }>
										{ vuln.Severity }
									</span>
								</td>
								<td>{ vuln.Description }</td>
								<td>{ vuln.Version }</td>
							</tr>
						}
					</tbody>
				</table>
			</div>
		</div>
	</div>
}

templ MalwareTab(malwareDetections []MalwareDetection) {
	<div class="tab-pane fade" id="malware" role="tabpanel" aria-labelledby="malware-tab">
		<div class="card mt-4">
			<div class="card-header">
				<h5 class="mb-0 text-white">Malware Detection</h5>
			</div>
			<div class="card-body">
				if len(malwareDetections) > 0 {
					<table class="table table-striped" id="malwareTable">
						<thead>
							<tr>
								<th>Package</th>
								<th>Type</th>
								<th>Detection Source</th>
								<th>Details</th>
							</tr>
						</thead>
						<tbody>
							for _, malware := range malwareDetections {
								<tr class="">
									<td>{ fmt.Sprintf("%s@%s", malware.Package, malware.Version) }</td>
									<td>
										<span class={ fmt.Sprintf("badge %s", getMalwareBadgeClass(malware.Type)) }>
											{ malware.Type }
										</span>
									</td>
									<td>{ malware.Source }</td>
									<td>{ malware.Details }</td>
								</tr>
							}
						</tbody>
					</table>
				} else {
					<div class="alert alert-success">
						<i class="bi bi-check-circle"></i> No malware detected in the scanned packages.
					</div>
				}
			</div>
		</div>
	</div>
}

templ PopularityTab(metrics []PopularityMetric) {
	<div class="tab-pane fade" id="popularity" role="tabpanel" aria-labelledby="popularity-tab">
		<div class="card">
			<div class="card-header">
				<h5 class="mb-0 text-white">Popularity Metrics</h5>
			</div>
			<div class="card-body">
				if len(metrics) > 0 {
					<table class="table table-striped" id="popularityTable">
						<thead>
							<tr>
								<th>Package</th>
								<th>Downloads</th>
								<th>Stars</th>
								<th>Contributors</th>
								<th>Last Updated</th>
							</tr>
						</thead>
						<tbody>
							for _, metric := range metrics {
								<tr>
									<td>{ metric.Package + "@" + metric.Version }</td>
									<td>{ fmt.Sprintf("%d", metric.Downloads) }</td>
									<td>{ fmt.Sprintf("%d", metric.Stars) }</td>
									<td>{ fmt.Sprintf("%d", metric.Contributors) }</td>
									<td>{ metric.LastUpdated }</td>
								</tr>
							}
						</tbody>
					</table>
				} else {
					<div class="alert alert-info">
						<i class="bi bi-info-circle me-2"></i>No popularity metrics available.
					</div>
				}
			</div>
		</div>
	</div>
}

templ PolicyViolationsTab(policyViolations []PolicyViolation) {
  <div class="tab-pane fade" id="policy" role="tabpanel" aria-labelledby="policy-tab">
    <div class="card mt-3">
      <div class="card-header">
        <h5 class="text-white"><i class="bi bi-shield-exclamation text-white"></i> Policy Violations</h5>
      </div>
      <div class="card-body">
        <table class="table table-striped">
          <thead>
            <tr>
              <th>Policy Violated</th>
              <th>Package</th>
              <th>Version</th>
              <th>Solution</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            for _, event := range policyViolations {
              <tr>
                <td>{event.PolicyName}</td>
                <td>{event.PackageName}</td>
                <td>{event.PackageVersion}</td>
                <td>
                  <span>
                    {event.Solution}
                  </span>
                </td>
                <td>{event.Description}</td>
              </tr>
            }
          </tbody>
        </table>
        if len(policyViolations ) == 0 {
          <div class="text-white">No policy violations detected.</div>
        }
      </div>
    </div>
  </div>
}
